package sy6_Behavioral_Pattern.command;
/*
 * 命令模式是对命令进行抽象与实现，作为命令调用（发送）者与接收者之间的中间层，实现解耦。
 * 角色1：命令接收者Receiver，定义了与请求相关的操作方法action()。
 * 角色2：抽象命令Command，一般设计为抽象类，定义了抽象方法execute()。
 * 角色3：具体命令ConcreteCommand，继承Command，关联一个Receiver，重写的抽象方法通过Receiver对象完成。
 * 角色4：命令请求的调用者Invoker，聚合Command。
 * Client：创建Receiver对象，使用ConcreteCommand创建Command的实例
 * 要点：execute()是对Receiver的action()方法的抽象，因为不同的接收者有不同的操作。
 *
 * 参考视频：https://www.bilibili.com/video/BV1YE411u7e2?from=search&seid=14900137818785556405
 */

class Receiver { //角色1：接收者Receiver
	public void action() {  //接收与请求相关的操作
		System.out.println("Receiver is working.");
	}
}

abstract class Command { //角色2：抽象命令Command
	 public abstract void  execute(); //接收者工作方法的抽象
}

class ConcreteCommand extends Command { //角色3：命令发送者ConcreteCommand
	private Receiver receiver; //体现关联
	private String state="命令1未执行";

	public ConcreteCommand(Receiver receiver) {  //构造器注入
		this.receiver = receiver;
		System.out.println(state);
	}

	@Override
	public void execute() {  //重写抽象方法
		receiver.action();  //调用命令接收者方法
		state="命令1已执行";
		System.out.println(state);
	}
}

/*class ConcreteCommand2 extends Command { //供扩展时使用
	private Receiver receiver; //体现关联
	private String state="命令2未执行";

	public ConcreteCommand2(Receiver receiver) {  //构造器注入
		this.receiver = receiver;
		System.out.println(state);
	}

	@Override
	public void execute() {  //重写抽象方法
		state="命令2已执行";
		receiver.action();  //调用命令接收者方法
		System.out.println(state);
	}
}*/

class Invoker { //角色4：调用者

	private Command command; //Invoker聚合Command

	public void setCommand(Command command) { //setter
		this.command = command;
	}

	public void call() {  //定义请求方法
		command.execute();  //调用命令者完成
	}
}

public class Client {  //客户端
	public static void main(String[] args) {
		System.out.println("=====使用命令模式=====");
		//创建命令接收者；Client关联Receiver
		Receiver receiver = new Receiver();
		//创建命令请求者
		Invoker invoker = new Invoker();
		//调用Setter方法
		invoker.setCommand(new ConcreteCommand(receiver));
		//由请求者发送命令（执行）
		invoker.call();

		 //非命令模式（直接方式）不使用Invoker类
		System.out.println("\n====不使用命令模式====");
		receiver.action();

		//好处：增加新的具体命令类，不必修改系统已有的类。
		/*System.out.println("=======================");
		//使用新的具体命令；需要将取消类ConcreteCommand2定义的注释
		invoker.setCommand(new ConcreteCommand2(receiver));
		invoker.call();*/
	}
}
